package com.example.xcService.pojo.channels.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.xcService.pojo.channels.ChannelResult;
import com.example.xcService.pojo.channels.ChannelService;
import com.example.xcService.pojo.tool.HttpTool;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.regex.Pattern;

/*
* 杭州点点
* */
@Slf4j
public class Plugin_ECARD_P018 implements ChannelService {


    @Override
    public ChannelResult QueryBalance(JSONObject apiConfig) {
        System.out.println("成功调用了QueryBalance");
        return  ChannelResult.success("success");
    }

        /*
        tranid	String(32)	是	商户订单号[商户唯一流水号]
        coopid	String(32)	是	商户号
        proid	String(32)	是	商品编号
        quantity	int	是	充值件数
        price	int	是	面值，单位“元”
        account	String(64)	是	充值帐号（卡密订单，默认为：card）
        asyncurl	String(128)	是	回调地址,用来通知对接商户订单的状态
        ipaddr	String(32)	是	买家购买IP地址
        sign	String(32)	是	签名字串(见注意事项)
        */

    @Override
    public ChannelResult Submit(JSONObject apiConfig, Map<String, Object> data) {
        try {
            String AccountVal = String.valueOf(data.get("AccountVal"));
            if ( !checkQQNum(AccountVal)) {
                if(Pattern.matches("^1[3456789]\\d{9}$", AccountVal) != true){
                    return ChannelResult.FAILED("号码异常，订单失败");
                }
            }
            String amount = "1";
            String[] split = String.valueOf(data.get("SUPProductId")).split("_");
            if (split.length == 2) {
                amount = split[1];
            }
            LinkedHashMap<String, String> params = new LinkedHashMap<>();
            params.put("tranid", String.valueOf(data.get("ChannelOrderCode")));
            params.put("coopid", apiConfig.getString("UserId"));
            params.put("proid", String.valueOf(data.get("SUPProductId")));
            params.put("quantity", amount);
            BigDecimal priceDouble = new BigDecimal(String.valueOf(data.get("PurchasePrice")));
            int price = priceDouble.intValue();
            params.put("price", String.valueOf(price));
            params.put("account", AccountVal);
            params.put("asyncurl", "http://120.26.223.111:9090/");//回调地址-无回调地址
            params.put("ipaddr", "120.26.223.111");
            String secretKey = apiConfig.getString("secretKey");
            String sign = generateSign(params, secretKey);
            params.put("sign", sign);
            String submitURL = apiConfig.getString("SubmitURL");
            String res = HttpTool.sendGetGBK(submitURL, params);
            Map<String, String> responseMap = parseXmlResponse(res);
            String orderStatus = responseMap.get("orderStatus");//订单状态-作为订单失败或成功的判断标准
            String failedCode = responseMap.get("failedCode");//失败码  (不作为订单失败或成功的判断标准)
            String failedReason = responseMap.get("failedReason");//失败原因

            if (failedCode.equals("0301")) {
                log.info("订单重复");
                return ChannelResult.error("订单重复");
            }
            if (orderStatus.equals("SUCCESS")) {
                return ChannelResult.success("充值成功");
            }
            if (orderStatus.equals("UNDERWAY")) {
                return ChannelResult.IN_PROCESS("充值中");
            }
            if (orderStatus.equals("FAILED") || orderStatus.equals("CANCEL")) {
                log.info("充值失败：" + failedCode + "##" + failedReason);
                return ChannelResult.FAILED("充值失败");
            }
            log.info("订单创建失败或请求失败：" + failedCode + "##" + failedReason);
            return ChannelResult.error(failedCode, failedReason);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("杭州点点接口异常");
            return ChannelResult.error("杭州点点接口异常");
        }
    }

    @Override
    public ChannelResult Query(JSONObject apiConfig, Map<String, Object> data) {
       try {
           LinkedHashMap<String, String> paramas = new LinkedHashMap<>();
           paramas.put("coopid", apiConfig.getString("UserId"));
           paramas.put("tranid",String.valueOf(data.get("ChannelOrderCode")));
           String secretKey = apiConfig.getString("secretKey");
           String sign = generateSign(paramas, secretKey);
           paramas.put("sign",sign);

           String queryUrl = apiConfig.getString("QueryUrl");

           String res = HttpTool.sendGetGBK(queryUrl, paramas);
           Map<String, String> xmlResponse = parseXmlResponse(res);
           String orderStatus = xmlResponse.get("orderStatus");
           String failedCode = xmlResponse.get("failedCode");
           String failedReason = xmlResponse.get("failedReason");

           if (failedCode.equals("0301")) {
               log.info("订单重复");
               return ChannelResult.error("订单重复");
           }
           if (orderStatus.equals("SUCCESS")) {
               return ChannelResult.success("充值成功");
           }
           if (orderStatus.equals("UNDERWAY")) {
               return ChannelResult.IN_PROCESS("充值中");
           }
           if (orderStatus.equals("FAILED") || orderStatus.equals("CANCEL")) {
               log.info("充值失败：" + failedCode + "##" + failedReason);
               return ChannelResult.FAILED("充值失败");
           }
           log.info("订单创建失败或请求失败：" + failedCode + "##" + failedReason);
           return ChannelResult.error(failedCode, failedReason);
       }catch (Exception e) {
           e.printStackTrace();
           return ChannelResult.error("杭州点点接口异常");
       }
    }



    @Override
    public ChannelResult Notify(JSONObject apiConfig, Map<String, Object> data) {
        System.out.println("成功调用了Notify");
        return  ChannelResult.success("success");
    }


    public static String generateSign(Map<String, String> params, String secretKey) throws UnsupportedEncodingException {
        // 将参数按照ASCII码顺序排序
        List<Map.Entry<String, String>> sortedParams = new ArrayList<>(params.entrySet());
        sortedParams.sort(Comparator.comparing(Map.Entry::getKey));

        // 拼接参数键值对
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (value != null && !value.isEmpty()) {
                sb.append(key).append(value);
            }
        }

        // 添加商户密钥
        sb.append(secretKey);

        // 计算MD5摘要
        byte[] digest = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            digest = md.digest(sb.toString().getBytes("GBK"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        // 将摘要转换为十六进制字符串
        StringBuilder sign = new StringBuilder();
        if (digest != null) {
            for (byte b : digest) {
                sign.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3));
            }
        }

        return sign.toString();
    }

    public static Map<String, String> parseXmlResponse(String xmlResponse) throws Exception {
        // 创建DOM解析器工厂
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();

        // 将XML响应转化为输入流
        ByteArrayInputStream inputStream = new ByteArrayInputStream(xmlResponse.getBytes("GBK"));

        // 解析XML响应
        Document document = builder.parse(inputStream);

        // 获取根节点
        Element rootElement = document.getDocumentElement();

        // 获取子节点列表
        NodeList nodeList = rootElement.getChildNodes();

        HashMap<String, String> map = new HashMap<>();
        // 遍历子节点列表
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);

            // 判断节点类型是否为元素节点
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;

                // 获取节点名称和节点值
                String paramName = element.getNodeName();
                String paramValue = element.getTextContent();
                map.put(paramName,paramValue);
                // 输出参数名称和对应的值
                log.info("杭州点点响应参数："+paramName + ": " + paramValue);
            }
        }
        return map;

    }

    private static boolean checkQQNum(String s) {
        boolean flag = false;
        if (s.length() >= 5 && s.length() <= 15 && !s.startsWith("0")) {
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i);
                if (ch >= '0' && ch <= '9') {
                    flag = true;
                } else {
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }


}
